<template>
  <div>
    <!-- 分类参数组件 -->
    <!-- 一、面包屑导航 Breadcrumb 面包屑-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>参数列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 二、Card 组件卡片区域 -->
    <el-card class="box-card">
      <!--Ⅱ、1、头部警告提示框  + Alert 警告组件，用于页面中展示重要的提示信息。  -->
      <el-alert
        show-icon
        title="注意: 只允许为第三级分类设置相关参数!"
        type="warning"
        :closable="false"
      ></el-alert>

      <!--Ⅱ、2、选择商品分类区域  + layout 栅格布局组件 +  Cascader 级联选择器组件-->
      <el-row class="cat_opt">
        <el-col>
          <span>选择商品分类: </span>
          <!-- 选择商品分类的级联选择跨框 -->
          <el-cascader
            v-model="selectedCateKeys"
            :options="goodsCateList"
            :props="cateProps"
            @change="handleChange"
          >
          </el-cascader>
          <!-- options:绑定数据源  change：当选中节点变化时触发 -->
        </el-col>
      </el-row>

      <!--Ⅱ、3、Tabs 标签页-切换tab栏 -->
      <el-tabs v-model="activeName" @tab-click="handleTabClick">
        <!--3、1 添加动态参数的面板 -->
        <el-tab-pane label="动态参数" name="many">
          <!-- （1）添加参数的按钮 -->
          <el-button
            type="primary"
            size="mini"
            :disabled="isBtnDisabled"
            @click="showAddParams"
            >动态参数</el-button
          >
          <!-- （2）动态参数表格 -->
          <el-table :data="manyTableData" style="width: 100%" border stripe>
            <!-- 展开列 -->
            <el-table-column type="expand">
              <!-- 作用域插槽 + tag标签 + v-for循环 -->
              <!-- close	关闭 Tag 时触发的事件 -->
              <template slot-scope="scope">
                <!--Ⅰ 循环渲染Tag标签 -->
                <el-tag
                  v-for="(item, tagindex) in scope.row.attr_vals"
                  :key="tagindex"
                  closable
                  @close="tagHandleClose(tagindex, scope.row)"
                >
                  {{ item }}
                </el-tag>
                <!--Ⅱ 控制按钮与文本框的切换显示 -->
                <!-- Ⅱ、1 输入的文本框 -->
                <!-- keyup.enter.native鼠标抬起，按年enter键时触发；文本框失去焦点触发 ，scope.row当前行的数据-->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                >
                </el-input>
                <!-- Ⅱ、2 添加按钮 -->
                <el-button
                  v-else
                  class="button-new-tag"
                  size="small"
                  @click="showInput(scope.row)"
                  >+ New Tag</el-button
                >
              </template>
            </el-table-column>
            <!-- 索引列 -->
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column
              prop="attr_name"
              label="参数名称"
              width="180"
            ></el-table-column>
            <!-- 操作列 -->
            <el-table-column label="操作">
              <!-- 作用域插槽 + button图标按钮 -->
              <template slot-scope="scope">
                <el-button
                  type="primary"
                  icon="el-icon-edit"
                  size="mini"
                  @click="showEditDialog(scope.row.attr_id)"
                  >编辑</el-button
                >
                <el-button
                  type="danger"
                  icon="el-icon-delete"
                  size="mini"
                  @click="delParamsById(scope.row.attr_id)"
                  >删除</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <!--3、2 添加静态属性的面板 -->
        <el-tab-pane label="静态属性" name="only">
          <!-- （1）添加属性的按钮 -->
          <el-button
            type="primary"
            size="mini"
            :disabled="isBtnDisabled"
            @click="showAddParams"
            >静态属性</el-button
          >

          <!-- （2）静态属性的表格 -->
          <el-table :data="onlyTableDate" style="width: 100%" border stripe>
            <!-- 展开列 -->
            <el-table-column type="expand">
              <!-- 作用域插槽 + tag标签 + v-for循环 -->
              <!-- close	关闭 Tag 时触发的事件 -->
              <template slot-scope="scope">
                <!--Ⅰ 循环渲染Tag标签 -->
                <el-tag
                  v-for="(item, tagindex) in scope.row.attr_vals"
                  :key="tagindex"
                  closable
                  @close="tagHandleClose(tagindex, scope.row)"
                >
                  {{ item }}
                </el-tag>
                <!--Ⅱ 控制按钮与文本框的切换显示 -->
                <!-- Ⅱ、1 输入的文本框 -->
                <!-- keyup.enter.native鼠标抬起，按年enter键时触发；文本框失去焦点触发 ，scope.row当前行的数据-->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                >
                </el-input>
                <!-- Ⅱ、2 添加按钮 -->
                <el-button
                  v-else
                  class="button-new-tag"
                  size="small"
                  @click="showInput(scope.row)"
                  >+ New Tag</el-button
                >
              </template>
            </el-table-column>
            <!-- 索引列 -->
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column
              prop="attr_name"
              label="属性名称"
              width="180"
            ></el-table-column>
            <!-- 操作列 -->
            <el-table-column label="操作">
              <!-- 作用域插槽 + button图标按钮 -->
              <template slot-scope="scope">
                <el-button
                  type="primary"
                  icon="el-icon-edit"
                  size="mini"
                  @click="showEditDialog(scope.row.attr_id)"
                  >编辑</el-button
                >
                <el-button
                  type="danger"
                  icon="el-icon-delete"
                  size="mini"
                  @click="delParamsById(scope.row.attr_id)"
                  >删除</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <!-- 按钮禁用
                重点：2个按钮是否禁用
                方法：通过计算属性，根据存储级联选择框选中项Id值的数组长度是否等于3，是否选中3级分类，来决定2个按钮是否禁用；按钮绑定属性 ：disabled='isBtnDisabled'
             -->

        <!-- 展开列：
        通过设置 type="expand" 和 Scoped slot 可以开启展开行功能，
        el-table-column 的模板会被渲染成为展开行的内容 
        -->
      </el-tabs>
    </el-card>

    <!-- 4、添加动态参数、静态属性共用同一个Dialog 弹出对话框，利用计算属性 -->
    <el-dialog
      @close="addDialogClose"
      :title="'添加' + titleText"
      :visible.sync="addDialogVisible"
      width="50%"
    >
      <!-- 添加数据的form表单 -->
      <el-form
        :model="addForm"
        :rules="addFormRules"
        ref="addFormRef"
        label-width="100px"
      >
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="addForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <!-- 底部 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addParams">确 定</el-button>
      </span>
    </el-dialog>

    <!--5、 修改对话框 -->
    <el-dialog
      @close="editDialogClose"
      :title="'修改' + titleText"
      :visible.sync="editDialogVisible"
      width="50%"
    >
      <!-- 添加数据的form表单 -->
      <el-form
        :model="editForm"
        :rules="editFormRules"
        ref="editFormRef"
        label-width="100px"
      >
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="editForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <!-- 底部 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editParams">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "Params",
  data() {
    return {
      //1、保存，请求获取到的商品分类数据列表，默认为空，请求获取后被赋值
      //作为--级联选择框的渲染页面的数据源
      goodsCateList: [],

      //2、1-级联选择框的配置对象
      cateProps: {
        value: "cat_id", //分类 ID
        label: "cat_name", //分类名称
        children: "children", //选项的子选项
        expandTrigger: "hover",
      },

      //2、2-级联选择框双向绑定到的id数组：存储级联框选中的该项Id值，此次要求只能选中三级列表项的Id
      selectedCateKeys: [1,3,6],

      //3、被激活选中的当前tab栏页的name
      //点击，当前被选中的标签页，默认激活选中、展示第一页
      activeName: "many",

      //存储-获取到的是动态参数请求的数据
      manyTableData: [],
      //存储-获取到的是静态属性请求的数据
      onlyTableDate: [],

      //4、控制添加动态参数、静态属性的对话框的显示与隐藏
      addDialogVisible: false,
      //存储、绑定添加参数的表单数据对象
      addForm: {
        attr_name: "",
      },
      //表单验证规则对象
      addFormRules: {
        attr_name: [
          { required: true, message: "请输入参数名称", trigger: "blur" },
        ],
      },

      // 5、--------修改对话框--------
      //控制修改对话框的显示与隐藏
      editDialogVisible: false,
      //修改对话框绑定的数据表单对象，双向绑定，存储修改的数据
      editForm: {
        attr_name: "",
      },
      //表单验证规则对象
      editFormRules: {
        attr_name: [
          { required: true, message: "请输入参数名称", trigger: "blur" },
        ],
      },

      /*   // ----------3---tag标签------------
      // 控制按钮与文本框的切换显示与隐藏
      inputVisible:false,
      // 双向绑定文本框中输入的值
      inputValue:'',
 */
    };
  },
  created() {
    //生命周期创建阶段：created--在初始化vue实例上的属性和方法之后 执行； created: function ()
    //1、一打开页面，立即调用获取渲染所有的商品分类列表数据
    this.getgoodCateList();
  },
  methods: {
    //1、发起请求，获取商品分类列表数据  1.6.1接口
    /* 请求参数：此次都可不传，①type,默认渲染三级，②此次不需要分页，可不传pagenum、pagesize
    type:[1,2,3],【可选参数】如果不传递，则默认获取所有级别的分类
    pagenum当前页码值【可选参数】如果不传递，则默认获取所有分类
    pagesize每页显示多少条数据【可选参数】如果不传递，则默认获取所有分类 */
    async getgoodCateList() {
      const ret = await this.$http.get("categories");
      const res = ret.data;
      console.log(res);
      //判断是否成功获取商品分类数据列表
      if (res.meta.status !== 200) {
        return this.$message.error("获取商品分类列表失败！" + res.meta.msg);
      }
      this.$message.success("成功获取商品分类列表");
      //把获取到的商品分类数据列表存储到data内--作为：级联选择框的渲染页面的数据源
      this.goodsCateList = res.data;
    },

    //2、级联选择框选中项变化时，触发的函数
    handleChange() {
      //打印级联框选中项的Id值--数组,默认是3级可以选中
      console.log(this.selectedCateKeys);
      this.getParamsData();
    },

    //3、tab切换栏、tab点击时被触发的处理函数
    //@tab-click 点击被选中时触发
    handleTabClick() {
      console.log(this.activeName);
      this.getParamsData();
    },

    //2/3 -----------------抽离出来的 请求动态参数 与 静态属性 参数 的列表数据 函数，---------------
    //被上面通过级联框选中项变化触发事件的请求，tab面板切换发起的请求分别触发，获取的数据
    async getParamsData() {
      //注意：要求只求选中修改3级分类的参数配置
      //通过级联框选中项绑定的Id值数组的长度是否等于3，判断选中的是否是3级分类

      //证明选中的不是3级分类
      if (this.selectedCateKeys.length !== 3) {
        //若长度不等于3，重置数组为空，令页面中级联框处于未选中的状态
        this.selectedCateKeys = [];
        //同时，清空所有动态参数与静态属性--表格数据
        this.manyTableData = [];
        this.onlyTableDate = [];
        return this.$message.info("只能选中修改3级分类的参数！");
      }
      //证明选中的是3级分类
      console.log(this.selectedCateKeys);
      //3、根据所选分类的Id,和当前所处的面板，发请求，获取对应的参数
      const ret = await this.$http.get(`categories/${this.cateId}/attributes`, {
        params: { sel: this.activeName },
      });
      //Ⅰ、data中绑定的是，请求动态参数，activeName='many'，默认
      //Ⅱ、当点击切换到静态属性面板时，再请求静态属性列表
      const res = ret.data;
      console.log(res);

      //判断获取参数列表是否成功
      if (res.meta.status !== 200) {
        return this.$message.error("获取参数列表失败！" + res.meta.msg);
      }
      this.$message.success("成功获取参数列表");
      //   console.log(res.data);
      //此时数据中获取到的attr_vals是字符串

      // ----------3---tag标签------------
      // 重点；循环，为每一项参数数据中的attr_vals，重新赋值，变为数组
      res.data.forEach((item) => {
        //（1）若item.attr_vals的值不是空的，直接渲染tag标签；是空的，直接返回空数组（解决新加参数无相关参数信息，渲染出空的字符串tag标签问题）
        item.attr_vals = item.attr_vals ? item.attr_vals.split(",") : [];
        // （2）控制每行按钮与文本框的切换显示与隐藏
        item.inputVisible = false;
        // （3）每行双向绑定文本框中输入的值
        item.inputValue = "";
      });
      console.log(res.data); //此时数据中获取到的attr_vals是数组

      //判断获取的是动态参数还是静态属性的数据，分别存储
      if (this.activeName === "many") {
        //获取到的是动态参数请求的数据
        this.manyTableData = res.data;
      } else {
        //获取到的是静态属性请求的数据
        this.onlyTableDate = res.data;
      }
    },

    // ------------3 tag标签--------------
    //Ⅱ、1  监听文本框失去焦点，或按下enter键 都会触发的事件,如新增tag标签
    async handleInputConfirm(row) {
      console.log(row); //当前行的所有数据
      //（1）判断用户是否输入内容
      if (row.inputValue.trim().length === 0) {
        //去掉空格，input值长度 = 0，证明没有输入内容
        row.inputValue = ""; //重置表单，清空
        row.inputVisible = false; //隐藏输入框
        return this.$message.info("没人输入内容");
      }
      //（2）若没有return，证明用户输入了内容，加入attr_vals数组内渲染
      row.attr_vals.push(row.inputValue.trim());
      row.inputValue = ""; //清空文本框内的值
      row.inputVisible = false; //隐藏文本框

      //（3）发起请求，编辑提交参数,把此次操作保存同步到后台数据库 1.7.5接口
      //注意：服务器中attr_vals存储的是字符串，我们要重新把数组再转为字符串存储
      const ret = await this.$http.put(
        `categories/${this.cateId}/attributes/${row.attr_id}`,
        {
          attr_name: row.attr_name, //新属性的名字
          attr_sel: row.attr_sel, //属性的类型[many或only]
          attr_vals: row.attr_vals.join(","), //参数的属性值
        }
      );
      const res = ret.data;
      console.log(res);
      //(4)判断是否编辑-更新参数成功
      if (res.meta.status !== 200) {
        return this.$message.error("添加-更新参数失败！" + res.meta.msg);
      }
      this.$message.success("提交-添加-更新参数成功！");
    },

    //Ⅱ、2 点击按钮，切换展示文本框
    showInput(row) {
      row.inputVisible = true;
      //this.$nextTick:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法，获取更新后的 DOM。
      this.$nextTick((_) => {
        //当页面上的元素被重新渲染之后，才会执行回调函数中待定
        //自动获取焦点
        this.$refs.saveTagInput.$refs.input.focus();
      });
    },
    //Ⅲ、监听tag标签参数 关闭close事件 ==>删除该项参数
    async tagHandleClose(tagindex, row) {
      console.log("attr_vals数组中删除该项参数的索引：" + tagindex);
      console.log("选中项的第3级分类参数的id:" + row.attr_id);
      console.log(row);

      //. 删除当前tag参数 +   put接口
      row.attr_vals.splice(tagindex, 1);
      //  将对attr_vals的操作保存到数据库，与Ⅰ、（3）代码相同，可提取出来
      const ret = await this.$http.put(
        `categories/${this.cateId}/attributes/${row.attr_id}`,
        {
          attr_name: row.attr_name, //新属性的名字
          attr_sel: row.attr_sel, //属性的类型[many或only]
          attr_vals: row.attr_vals.join(","), //参数的属性值
        }
      );
      const res = ret.data;
      console.log(res);
      //(4)判断是否编辑-更新参数成功
      if (res.meta.status !== 200) {
        return this.$message.error("删除参数失败！" + res.meta.msg);
      }
      this.$message.success("删除参数成功！");

      //此地，编辑添加--删除是请求同个接口 ---put
      
    },

    //4、点击确定，Dialog 弹出
    //添加动态参数、静态属性共用同一个Dialog 弹出对话框
    showAddParams() {
      //显示对话框
      this.addDialogVisible = true;
    },
    //监听对话框的关闭事件，清空上一次的验证规则结果
    addDialogClose() {
      this.$refs.addFormRef.resetFields();
    },
    //发起请求，提交填写的参数数据
    addParams() {
      //先进行预校验，验证填写的数据是否合法
      this.$refs.addFormRef.validate(async (valid) => {
        console.log("验证此次填写的参数数据是否合法：" + valid);
        if (!valid) {
          return this.$message.info("您填写的参数不符合要求！");
        }
        //验证通过，发起请求，提交数据
        const ret = await this.$http.post(
          `categories/${this.cateId}/attributes`,
          {
            attr_name: this.addForm.attr_name, //参数名称
            attr_sel: this.activeName, // [only,many],请求提交的是静态参数还是动态参数的数据
          }
        );
        const res = ret.data;
        console.log(res);
        //判断是否提交成功
        if (res.meta.status !== 201) {
          return this.$message.error("添加参数失败！" + res.meta.msg);
        }
        this.$message.success("成功添加参数！");

        //关闭对话框
        this.addDialogVisible = false;
        //重新请求，渲染动态参数列表、静态属性列表
        this.getParamsData();
      });
    },

    //5、 修改对话框
    //(1)点击编辑按钮，显示弹出框
    async showEditDialog(attr_id) {
      //(3)点击编辑，当前行数据 ，发起请求，根据 ID 查询参数
      const ret = await this.$http.get(
        `categories/${this.cateId}/attributes/${attr_id}`,
        {
          params: { attr_sel: this.activeName },
          //[only,many],请求的数据类型
        }
      );
      const res = ret.data;
      console.log(res);
      //判断是否请求-编辑成功
      if (res.meta.status !== 200) {
        return this.$message.error("获取当前参数信息失败！" + res.meta.msg);
      }
      this.$message.success("获取当前参数信息成功!");
      //把获取到的当前参数信息存储到 data内----默认填充到编辑表单中
      this.editForm = res.data;
      this.editDialogVisible = true;
    },
    //(2) 监听对话框的关闭事件，清空上一次的验证规则结果
    editDialogClose() {
      this.$refs.editFormRef.resetFields();
    },

    //(4)点击确定，发起请求，提交编辑的参数数据
    editParams() {
      //请求之前，先进行预校验
      this.$refs.editFormRef.validate(async (valid) => {
        console.log("此次编辑参数的校验结果：" + valid);
        //判断预校验是否通过
        if (!valid) {
          return this.$message.info("编辑的参数不符合要求！");
        }
        //预校验通过，发起请求

        const ret = await this.$http.put(
          `categories/${this.cateId}/attributes/${this.editForm.attr_id}`,
          {
            attr_name: this.editForm.attr_name, //新属性的名字
            attr_sel: this.activeName, //编辑提交的数据类型[many或only]
          }
        );
        const res = ret.data;
        console.log(res);
        //判断是否请求-编辑成功
        if (res.meta.status !== 200) {
          return this.$message.error("修改参数信息失败！" + res.meta.msg);
        }
        this.$message.success("修改参数信息成功！");

        //重新请求，渲染参数列表
        this.getParamsData();
        //关闭修改对话框
        this.editDialogVisible = false;
      });
    },

    //6、根据 当前参数的ID 删除该参数 + MessageBox 弹框
    async delParamsById(attr_id) {
      //删除前，询问是否删除
      const result = await this.$confirm(
        "此操作将永久删除该参数, 是否继续?",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      ).catch((err) => {
        return err;
      });

      //用户点击确定删除，得到字符串 confirm
      //用户点击取消删除，得到字符串 cancel
      console.log(result);
      //根据用户点击的结果，决定是否发起请求，删除参数
      if (result !== "confirm") {
        return this.$message.info("已取消删除参数！");
      }
      //发起请求，删除当前参数
      const { data: res } = await this.$http.delete(
        `categories/${this.cateId}/attributes/${attr_id}`
      );
      //判断是否成功删除该参数
      if (res.meta.status !== 200) {
        return this.$message.error("删除参数失败！" + res.meta.msg);
      }
      this.$message.success("已成功删除该参数");
      //重新请求，渲染参数列表
      this.getParamsData();
    },
  },

  //计算属性 ：2个按钮是否禁用；级联框选中项的3级分类的id值
  computed: {
    //(1)如果按钮需要被禁用，则返回true,否则返回false
    isBtnDisabled() {
      if (this.selectedCateKeys.length !== 3) {
        //没有选中第3级分类，禁用按钮
        return true;
      }
      return false;
    },

    //(2)当前选中的三级分类的id值，获取参数列表的请求参数，不能为空 1.7.1接口
    cateId() {
      if (this.selectedCateKeys.length === 3) {
        return this.selectedCateKeys[2]; //数组最后一个就是当前选中的三级分类id
      }
      return null; //没有选中三级分类，没有这个id值
    },

    //3、添加动态参数、静态属性共用同一个Dialog 弹出对话框
    titleText() {
      console.log(this.activeName);
      if (this.activeName === "many") {
        return "动态参数";
      } else {
        return "静态属性";
      }
    },
  },
};
</script>


<style lang="less" scoped>
.cat_opt {
  margin: 15px 0;
}
.el-tag {
  margin: 5px;
}
.input-new-tag {
  width: 120px;
}
</style>